package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseSearchDTO;
import com.tianji.api.vo.CataSimpleInfoVO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningPlanDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.mapper.LearningMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @Author whx
 * @Date 2024/11/22 18:18
 */
@Service
@RequiredArgsConstructor
public class LearningServiceImpl extends ServiceImpl<LearningMapper, LearningLesson> implements ILearningService {

    private final LearningMapper learningMapper;

    private final CourseClient courseClient;

    private final CatalogueClient catalogueClient;

    private final LearningRecordMapper learningRecordMapper;

    /**
     * 查看我最近正在学习的课程
     * @return
     */
    @Override
    public LearningLessonVO now() {
        // 查询当前用户
        Long userId = UserContext.getUser();

        // 根据userId获取正在学习的课程(最近一次学习的课程)
        LambdaQueryWrapper<LearningLesson> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LearningLesson::getUserId, userId);
        wrapper.eq(LearningLesson::getStatus, 1);
        wrapper.orderByDesc(LearningLesson::getLatestLearnTime);

        LearningLesson learningLesson = learningMapper.selectList(wrapper).get(0);

        // 判空
        if(ObjectUtil.isNull(learningLesson)){
            return null;
        }

        return ll2LLVo(learningLesson);
    }

    /**
     * 分页查询我的课表
     * @return
     */
    @Override
    public PageDTO<LearningLessonVO> page(PageQuery pageQuery) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.分页查询
        // select * from learning_lesson where user_id = #{userId} order by latest_learn_time limit 0, 5
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId) // where user_id = #{userId}
                .page(pageQuery.toMpPage("latest_learn_time", false));

        List<LearningLessonVO> lessonVOList = null;

        if(!ObjectUtil.isEmpty(page.getRecords())){
            // 不为空就遍历
             lessonVOList = page
                     .getRecords()
                     .stream()
                     .map(this::ll2LLVo)
                     .collect(Collectors.toList());
        }

        return PageDTO.of(page, lessonVOList);
    }

    /**
     * 根据id查询某课程学习状态
     * @param courseId
     * @return
     */
    @Override
    public LearningLessonVO getCourseId4LearningLessonVo(Long courseId) {
        LambdaQueryWrapper<LearningLesson> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LearningLesson::getCourseId, courseId);

        LearningLesson learningLesson = learningMapper.selectOne(wrapper);

        // 判空
        if(ObjectUtil.isNull(learningLesson)){
           return null;
        }

        return ll2LLVo(learningLesson);
    }

    /**
     * 创建学习计划
     * @param learningPlanDTO
     */
    @Override
    public void createPlans(LearningPlanDTO learningPlanDTO) {
        Long courseId = learningPlanDTO.getCourseId();
        Integer weekFreq = learningPlanDTO.getFreq();
        Long userId = UserContext.getUser();

        // 判断是修改还是新设置
        LearningLesson lesson = queryByUidAndCid(userId, userId);

        AssertUtils.isNotNull(lesson, "课程信息不存在！");

        // 根据课程id和用户id更新学习计划相关字段
        this.lambdaUpdate()
                .set(LearningLesson::getWeekFreq, weekFreq)
                .set(lesson.getPlanStatus() == 0,LearningLesson::getPlanStatus, 1)
                .eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, userId)
                .update();
    }


    /**
     * 查询我的学习记录
     * @param pageQuery
     * @return
     */
    @Override
    public LearningPlanPageVO pageMyStudyPlans(PageQuery pageQuery) {
        Long userId = UserContext.getUser();

        // 查询 当前用户 正在学习  的  课程  的  课程id 计划学习数量 学完的小节数 上次学习时间
        List<LearningLesson> lessonList = this.lambdaQuery()
                .select(LearningLesson::getId,
                        LearningLesson::getCourseId,
                        LearningLesson::getWeekFreq,
                        LearningLesson::getLearnedSections,
                        LearningLesson::getLatestLearnTime)
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, 1)
                .list();

        // 遍历得到每一条 当前用户 正在学习 的 课程
        List<LearningPlanVO> list = lessonList.stream().map(ll -> {

            LocalDate[] weekStartEndDates = getWeekStartEndDates(LocalDate.now());

            // 查询当前课程 的 本周完成情况
            LambdaQueryWrapper<LearningRecord> wrapper = Wrappers.<LearningRecord>lambdaQuery()
                    .eq(LearningRecord::getUserId, userId)
                    .eq(LearningRecord::getLessonId, ll.getId())
                    .eq(LearningRecord::getFinished, true)
                    .between(LearningRecord::getFinishTime, weekStartEndDates[0], weekStartEndDates[1]);

            // 查询该ll本周学习完成记录 几条
            List<LearningRecord> learningRecords = learningRecordMapper.selectList(wrapper);

            // 根据课程id查询课程name
            CourseSearchDTO courseInfo = courseClient.getSearchInfo(ll.getCourseId());

            Integer sections = courseInfo.getSections();
            String courseName = courseInfo.getName();

            LearningPlanVO learningPlanVO = new LearningPlanVO();
            learningPlanVO.setCourseId(ll.getCourseId());
            learningPlanVO.setCourseName(courseName);
            if(learningRecords.size() > ll.getWeekFreq()){
                learningPlanVO.setWeekLearnedSections(ll.getWeekFreq());
            }else {
                learningPlanVO.setWeekLearnedSections(learningRecords.size());
            }
            learningPlanVO.setWeekFreq(ll.getWeekFreq());
            learningPlanVO.setLearnedSections(ll.getLearnedSections());
            learningPlanVO.setSections(sections);
            learningPlanVO.setLatestLearnTime(ll.getLatestLearnTime());

            return learningPlanVO;

        }).collect(Collectors.toList());

        Integer weekFinished = 0;
        Integer weekTotalPlan = 0;

        for (LearningPlanVO planVO : list) {
            // 当本周学的超过该课程本周计划的
            if(planVO.getWeekLearnedSections() > planVO.getWeekFreq()){
                weekFinished = weekFinished + planVO.getWeekFreq();
            }else {
                weekFinished = weekFinished + planVO.getWeekLearnedSections();
            }
            weekTotalPlan = weekTotalPlan + planVO.getWeekFreq();
        }

        Page<LearningPlanVO> page = new Page<>(pageQuery.getPageNo(), pageQuery.getPageSize());

        LearningPlanPageVO learningPlanPageVO = new LearningPlanPageVO();
        learningPlanPageVO.setWeekFinished(weekFinished);
        learningPlanPageVO.setWeekTotalPlan(weekTotalPlan);
        learningPlanPageVO.pageInfo(PageDTO.of(page, list));
//        learningPlanPageVO.setWeekPoints();
        return learningPlanPageVO;
    }


    /**
     * 获取指定日期所在周的起始日期和结束日期
     * @param date 指定日期
     * @return 一个包含起始日期和结束日期的数组
     */
    public LocalDate[] getWeekStartEndDates(LocalDate date) {
        // 获取本周的第一天（周一）
        LocalDate startOfWeek = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        // 获取本周的最后一天（周日）
        LocalDate endOfWeek = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

        return new LocalDate[]{startOfWeek, endOfWeek};
    }


    /**
     * 根据userId和courseId查询学习的课程
     * @param userId
     * @param courseId
     * @return
     */
    private LearningLesson queryByUidAndCid(Long userId, Long courseId) {
        LearningLesson lesson = this.lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, userId)
                .one();

        return lesson;
    }


    /**
     * 从LearningLesson封装成LearningLessonVo
     * @param learningLesson
     * @return
     */
    private LearningLessonVO ll2LLVo(LearningLesson learningLesson){
        LearningLessonVO learningLessonVO = BeanUtils.toBean(learningLesson, LearningLessonVO.class);

        // 远程调用课程接口查询数据
        CourseSearchDTO searchInfo = courseClient.getSearchInfo(learningLesson.getCourseId());

        // 补充关于课程的字段
        learningLessonVO.setCourseName(searchInfo.getName());
        learningLessonVO.setCourseCoverUrl(searchInfo.getCoverUrl());
        learningLessonVO.setSections(searchInfo.getSections());

        learningLessonVO.setLatestSectionIndex(learningLesson.getLearnedSections());

        CataSimpleInfoVO cataSimpleInfoVO = catalogueClient.querySectionInfoById(learningLesson.getLatestSectionId());
        learningLessonVO.setLatestSectionName(cataSimpleInfoVO.getName());

        return learningLessonVO;
    }
}
